package com.qiongqi.datadir.utils.security;

import com.qiongqi.datadir.domain.Certificate;

import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import java.io.FileReader;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;

import static com.qiongqi.datadir.consts.Constants.UTF8;

/**
 * PEM文件解析
 */
public final class PEMUtils {

    /**
     * 读取PEM文件并返回证书/密钥信息, PEM文件内容如下:
     *   分支类型         |          输入PEM标识          |      输出对象           |         典型应用场景
     * X509Certificate  |      BEGIN CERTIFICATE       |    完整证书信息          |       HTTPS服务端证书验证
     * PrivateKey       |      BEGIN PRIVATE KEY       |     私钥对象            |         解密/签名操作
     * PublicKey        |      BEGIN PUBLIC KEY        |     公钥对象            |         加密/验签操作
     * PEMKeyPair       |      BEGIN RSA PRIVATE KEY   |     公钥+私钥对         |         自签名证书生成
     * @param filePath PEM文件路径
     * @return Certificate 包含证书或密钥信息的对象
     * @throws IOException 文件读取失败时抛出
     * @throws IllegalArgumentException 文件内容不兼容时抛出
     */
    public static Certificate readPemFile(String filePath) throws IOException {
        try (PEMParser parser = new PEMParser(new FileReader(filePath))) {
            Object obj = parser.readObject();
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
            //解析X.509证书分支(HTTPS服务端证书验证)
            if (obj instanceof X509Certificate) {
                X509Certificate cert = (X509Certificate) obj;
                return new Certificate(
                        cert.getSubjectDN().toString(),
                        cert.getPublicKey().getAlgorithm(),
                        cert.getIssuerDN().toString(),
                        cert.getSerialNumber(),
                        cert.getNotBefore(),
                        cert.getNotAfter(),
                        cert.getSigAlgName(),
                        new String(cert.getSignature(), UTF8),
                        cert.getPublicKey().toString(),
                        null,
                        "" + cert.getVersion()
                );
            }
            //解析私钥分支(解密/签名操作)
            else if (obj instanceof PrivateKey) {
                PrivateKey privateKey = (PrivateKey) obj;
                return new Certificate(
                        null, privateKey.getAlgorithm(), null,null,
                        null, null, "PRIVATE_KEY", null,
                        null, privateKey.toString(), null
                );
            }
            //解析公钥分支(加密/验签操作)
            else if (obj instanceof PublicKey) {
                PublicKey publicKey = (PublicKey) obj;
                return new Certificate(
                        null, publicKey.getAlgorithm(), null, null,
                        null, null, "PUBLIC_KEY", null,
                        publicKey.toString(), null, null
                );
            }
            //解析密钥对分支(自签名证书生成)
            else if (obj instanceof org.bouncycastle.openssl.PEMKeyPair) {
                org.bouncycastle.openssl.PEMKeyPair keyPair =
                        (org.bouncycastle.openssl.PEMKeyPair) obj;
                PrivateKey privateKey = converter.getPrivateKey(keyPair.getPrivateKeyInfo());
                PublicKey publicKey = converter.getPublicKey(keyPair.getPublicKeyInfo());
                return new Certificate(
                        null, publicKey.getAlgorithm(), null, null,
                        null, null, "KEY_PAIR", null,
                        publicKey.toString(), privateKey.toString(), null
                );
            } else {
                throw new IllegalArgumentException("不支持的PEM类型: " + obj.getClass());
            }
        }
    }
}
